#include <STC12C5A60S2.h>
#include<intrins.h>

sbit L1 = P1 ^ 7;
sbit L2 = P1 ^ 6;
sbit L3 = P3 ^ 1;
sbit L4 = P3 ^ 0;
sbit L5 = P3 ^ 3;
sbit L6 = P3 ^ 2;
sbit L7 = P3 ^ 5;
sbit L8 = P3 ^ 4;
sbit L9 = P3 ^ 6;
sbit L10 = P3 ^ 7;
sbit L11 = P2 ^ 5;
sbit L12 = P2 ^ 6;
sbit L13 = P2 ^ 4;
sbit L14 = P2 ^ 3;

sbit H1 = P0 ^ 0;
sbit H2 = P0 ^ 1;
sbit H3 = P0 ^ 2;
sbit H4 = P0 ^ 3;
sbit H5 = P0 ^ 4;
sbit H6 = P0 ^ 5;
sbit H7 = P0 ^ 6;
sbit H8 = P0 ^ 7;
sbit H9 = P2 ^ 2;
sbit H10 = P2 ^ 1;
sbit H11 = P2 ^ 0;
/********************************************************************/

#define SAMPLE_NUM 128
#define LOG 6
#define TIME 2048
#define FFT_OUT_MIN 0
#define FFT_OUT_MAX	7
#define ADC_POWER   0x80
#define ADC_FLAG    0x10
#define ADC_START   0x08
#define ADC_SPEEDH  0x40


unsigned char code BRTable[SAMPLE_NUM] =
{	0, 64, 32, 96, 16, 80, 48, 112,

	8, 72, 40, 104, 24, 88, 56, 120,

	4, 68, 36, 100, 20, 84, 52, 116,

	12, 76, 44, 108, 28, 92, 60, 124,

	2, 66, 34, 98, 18, 82, 50, 114,

	10, 74, 42, 106, 26, 90, 58, 122,

	6, 70, 38, 102, 22, 86, 54, 118,

	14, 78, 46, 110, 30, 94, 62, 126,

	1, 65, 33, 97, 17, 81, 49, 113,

	9, 73, 41, 105, 25, 89, 57, 121,

	5, 69, 37, 101, 21, 85, 53, 117,

	13, 77, 45, 109, 29, 93, 61, 125,

	3, 67, 35, 99, 19, 83, 51, 115,

	11, 75, 43, 107, 27, 91, 59, 123,

	7, 71, 39, 103, 23, 87, 55, 119,

	15, 79, 47, 111, 31, 95, 63, 127
};

char code sin_tabb[SAMPLE_NUM] = {0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70, 75, 80, 85, 89, 94, 98, 102,

                                  105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126, 126, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112,

                                  108, 105, 102, 98, 94, 89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30,

                                  -36, -42, -48, -54, -59, -65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121,

                                  -123, -124, -125, -126, -126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102,

                                  -98, -94, -89, -85, -80, -75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6
                                 };

char code cos_tabb[SAMPLE_NUM] = {127, 126, 126, 125, 124, 123, 121, 119, 117, 114, 112, 108, 105, 102, 98, 94,

                                  89, 85, 80, 75, 70, 65, 59, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, -6, -12, -18, -24, -30, -36, -42, -48, -54, -59,

                                  -65, -70, -75, -80, -85, -89, -94, -98, -102, -105, -108, -112, -114, -117, -119, -121, -123, -124, -125, -126, -

                                  126, -126, -126, -126, -125, -124, -123, -121, -119, -117, -114, -112, -108, -105, -102, -98, -94, -89, -85, -80,

                                  -75, -70, -65, -59, -54, -48, -42, -36, -30, -24, -18, -12, -6, 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 59, 65, 70,

                                  75, 80, 85, 89, 94, 98, 102, 105, 108, 112, 114, 117, 119, 121, 123, 124, 125, 126, 126
                                 };

xdata unsigned char result[128];

xdata unsigned char temp[128];

xdata unsigned char num[128];

unsigned char anum, timernum, timernum2, lednum3, Ltime, t;

unsigned char lednum[] = {0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};

int xdata FftReal[SAMPLE_NUM];

int xdata FftImage[SAMPLE_NUM];

unsigned char code musicdisplay[] = {
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    //??
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xeb, 0xe7, 0x81, 0xe7, 0xeb, 0xff,	 //
	0xff, 0xaf, 0xab, 0xa1, 0x8f, 0xaf, 0xff,	 //
	0xff, 0xff, 0xff,
	0xff, 0x81, 0xdf, 0xef, 0xdf, 0x81, 0xff, //M
	0xff, 0x81, 0xfd, 0xfd, 0xfd, 0x81, 0xff, //U
	0xff, 0x8d, 0xad, 0xad, 0xad, 0xa1, 0xff, //S
	0xff, 0x81, 0xff,   						       //I
	0xff, 0x81, 0xbd, 0xbd, 0xbd, 0xbd, 0xff, //C
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};

void delay(unsigned char a)
{
	unsigned int i;
	while (--a)
		for (i = 0; i < 50; i++);
}

void display(unsigned char i, unsigned char dat)
{
	unsigned char n;
	H1 = H2 = H3 = H4 = H5 = H6 = H7 = H8 = H9 = H10 = H11 = 0;
	for (n = 0; n < dat; n++)
	{
		switch (n)
		{
		case 0:
			H1 = 1;
			break;
		case 1:
			H2 = 1;
			break;
		case 2:
			H3 = 1;
			break;
		case 3:
			H4 = 1;
			break;
		case 4:
			H5 = 1;
			break;
		case 5:
			H6 = 1;
			break;
		case 6:
			H7 = 1;
			break;
		case 7:
			H8 = 1;
			break;
		case 8:
			H9 = 1;
			break;
		case 9:
			H10 = 1;
			break;
		case 10:
			H11 = 1;
			break;
		}
	}
	L1 = L2 = L3 = L4 = L5 = L6 = L7 = L8 = L9 = L10 = L11 = L12 = L13 = 1;
	switch (i - 1)
	{
	case 0:
		L1 = 0;
		break;
	case 1:
		L2 = 0;
		break;
	case 2:
		L3 = 0;
		break;
	case 3:
		L4 = 0;
		break;
	case 4:
		L5 = 0;
		break;
	case 5:
		L6 = 0;
		break;
	case 6:
		L7 = 0;
		break;
	case 7:
		L8 = 0;
		break;
	case 8:
		L9 = 0;
		break;
	case 9:
		L10 = 0;
		break;
	case 10:
		L11 = 0;
		break;
	case 11:
		L12 = 0;
		break;
	case 12:
		L13 = 0;
		break;
	case 13:
		L14 = 0;
		break;
	}
	delay(5);
	//P0=0xFF;
	//P1=0xFE;
	//P2=0xFF;
	//P3=0xFF;
}

void show_musicdisplay()
{
	unsigned char a, b, c;
	//for (b=0;b<62;b++)
	for (c = 0; c < 14; c++)
	{
		for (a = 0; a < 13; a++)
		{
			display(c, a);
			delay(200); delay(200); delay(200); delay(200);
			delay(200); delay(200); delay(200); delay(200);
		}
		delay(200); delay(200); delay(200); delay(200);
		delay(200); delay(200); delay(200); delay(200);
	}
}

void FFT_process()
{
	unsigned char i;
	for (i = 0; i < 24; i++)
	{
		if (result[i] < temp[i])
		{
			num[i]++;
			if (num[i] == 1)
			{
				if (temp[0] == 0 && temp[1] == 0 && temp[2] == 0 && temp[3] == 0 && temp[4] == 0 && temp[5] == 0 && temp[6] == 0 && temp[7] == 0 && temp[8] == 0 && temp[9] == 0 && temp[10] == 0 && temp[11] == 0 && temp[12] == 0 && temp[13] == 0 && temp[14] == 0 && temp[15] == 0 && temp[16] == 0 && temp[17] == 0 && temp[18] == 0 && temp[19] == 0 && temp[20] == 0 && temp[21] == 0 && temp[22] == 0 && temp[23] == 0 && temp[24] == 0);
				else
				{
					result[i] = --temp[i];
					num[i] = 0;
				}
			}
		}
		else
			num[i] = 0;
	}
}

void disp()
{
	timernum++;
	if (timernum == 15)
	{
		timernum = 1;
	}
	P0 = 0xFF;
	P1 = 0xFE;
	P2 = 0XFF;
	P3 = 0xFF;
	FFT_process();
	switch (timernum)
	{
	case 1:
		anum = result[0];
		L1 = 1;
		break;
	case 2:
		anum = result[1];
		L2 = 1;
		break;
	case 3:
		anum = result[2];
		L3 = 0;
		break;
	case 4:
		anum = result[3];
		L4 = 1;
		break;
	case 5:
		anum = result[4];
		L5 = 1;
		break;
	case 6:
		anum = result[5];
		L6 = 1;
		break;
	case 7:
		anum = result[6];
		L7 = 1;
		break;
	case 8:
		anum = result[7];
		L8 = 1;
		break;
	case 9:
		anum = result[8];
		L9 = 1;
		break;
	case 10:
		anum = result[9];
		L10 = 1;
		break;
	case 11:
		anum = result[10];
		L11 = 1;
		break;
	case 12:
		anum = result[11];
		L12 = 1;
		break;
	case 13:
		anum = result[12];
		L13 = 1;
		break;
	case 14:
		anum = result[13];
		L14 = 1;
		break;
	}
	if (anum >= 8)
		anum = FFT_OUT_MAX;
	display(timernum, anum * 10 / 7);
}

void ADC_init()
{
	P1ASF = 0x01;
	ADC_RES = 0;
	ADC_RESL = 0;
	ADC_CONTR = ADC_POWER | ADC_SPEEDH;
	delay(5);
}

float ADC_read()
{
	ADC_CONTR = ADC_POWER | ADC_SPEEDH  | ADC_START;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	while (!(ADC_CONTR & ADC_FLAG));
	ADC_CONTR &= ~ADC_FLAG;
	return (ADC_RES * 4 + ADC_RESL);
}

short sqrt_16(unsigned long M)
{
	unsigned int N, i;
	unsigned long tmp, ttp;
	if ( M == 0 )
		return 0;
	N = 0;
	tmp = (M >> 30);
	M <<= 2;
	if ( tmp > 1 )
	{
		N++;
		tmp -= N;
	}
	for ( i = 15; i > 0; i-- )
	{
		N <<= 1;
		tmp <<= 2;
		tmp += (M >> 30);
		ttp = N;
		ttp = (ttp << 1) + 1;
		M <<= 2;
		if ( tmp >= ttp )
		{
			tmp -= ttp;
			N ++;
		}
	}
	return N;
}

void FFT()
{
	register unsigned char i, bb, j, k, p;
	register short TR, TI, temp;
	unsigned long ulReal, ulImage;
	unsigned char max;
	for (i = 0; i < SAMPLE_NUM; i++)
	{
		FftReal[BRTable[i]] = ADC_read();
		FftImage[i] = 0;
	}
	for (i = 1; i <= LOG; i++)
	{
		bb = 1;
		bb <<= (i - 1);
		for (j = 0; j <= bb - 1; j++)
		{
			p = 1;
			p <<= (LOG - i);
			p = p * j;
			for (k = j; k < SAMPLE_NUM; k = k + 2 * bb)
			{
				TR = FftReal[k];
				TI = FftImage[k];
				temp = FftReal[k + bb];
				FftReal[k] = FftReal[k] + ((FftReal[k + bb] * cos_tabb[p]) >> 7) + ((FftImage[k + bb] * sin_tabb[p]) >> 7);
				FftImage[k] = FftImage[k] - ((FftReal[k + bb] * sin_tabb[p]) >> 7) + ((FftImage[k + bb] * cos_tabb[p]) >> 7);
				FftReal[k + bb] = TR - ((FftReal[k + bb] * cos_tabb[p]) >> 7) - ((FftImage[k + bb] * sin_tabb[p]) >> 7);
				FftImage[k + bb] = TI + ((temp * sin_tabb[p]) >> 7) - ((FftImage[k + bb] * cos_tabb[p]) >> 7);
				FftReal[k] >>= 1;
				FftImage[k] >>= 1;
				FftReal[k + bb] >>= 1;
				FftImage[k + bb] >>= 1;
			}
		}
	}
	for (i = 0; i < 24; i++)
	{
		ulReal = FftReal[i + 1];
		ulReal *= ulReal;
		ulImage = FftImage[i + 1];
		ulImage *= ulImage;
		result[i] = sqrt_16(ulReal + ulImage);
	}
	while (result[i] == FFT_OUT_MIN)
	{
		for (i = 0; i < 24; i++)
		{
			result[i] = result[i] + 1;
		}
	}
	for (i = 0; i < 24; i++)
	{
		if (result[i] > FFT_OUT_MAX)
		{
			result[i] = FFT_OUT_MAX;
			if (result[i] > max)
				max = result[i];
		}
	}
}

void init()
{
	P0M1 = 0X00;		P0M0 = 0XFF;
	P3M1 = 0X00;	  P3M0 = 0X00;
	P1M1 = 0X00;		P1M0 = 0X00;
	P2M1 = 0X00;		P2M0 = 0X07;

	ADC_init();

	TMOD = 0x01;
	TH0 = (65535 - TIME) / 256;
	TL0 = (65535 - TIME) % 256;
	EA = 1;
	ET0 = 1;
	show_musicdisplay();
	TR0 = 1;
}

void main()
{
	init();
	while (1)
	{
		FFT();
		//show_musicdisplay();
	}
}

void timer0() interrupt 1
{
	unsigned char i;
	TH0 = (65535 - TIME) / 256;
	TL0 = (65535 - TIME) % 256;
	t++;
	if (t == 24)
	{
		for (i = 0; i < 24; i++)
			temp[i] = result[i];
		t = 0;
	}
	disp();
}